/**
 * EP字段加密捕获脚本
 * 专门用于分析ep字段的加密方式
 */

console.log("\n" + "=".repeat(80));
console.log("EP字段加密分析 - 数美SDK");
console.log("=".repeat(80) + "\n");

// 存储捕获的数据
var capturedData = {
    aesKeys: [],
    rsaPlaintext: [],
    rsaCiphertext: [],
    epValues: []
};

function bytesToHex(bytes) {
    let hex = "";
    for (let i = 0; i < bytes.length; i++) {
        const byte = bytes[i] & 0xFF;
        hex += ("0" + byte.toString(16)).slice(-2);
    }
    return hex;
}

function bytesToString(bytes) {
    let str = "";
    for (let i = 0; i < bytes.length; i++) {
        const c = bytes[i] & 0xFF;
        if (c >= 32 && c <= 126) {
            str += String.fromCharCode(c);
        } else {
            str += ".";
        }
    }
    return str;
}

function base64Encode(bytes) {
    const base64chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
    let result = '';
    let i = 0;
    
    while (i < bytes.length) {
        const b1 = bytes[i++] & 0xFF;
        const b2 = i < bytes.length ? bytes[i++] & 0xFF : 0;
        const b3 = i < bytes.length ? bytes[i++] & 0xFF : 0;
        
        const enc1 = b1 >> 2;
        const enc2 = ((b1 & 3) << 4) | (b2 >> 4);
        const enc3 = ((b2 & 15) << 2) | (b3 >> 6);
        const enc4 = b3 & 63;
        
        result += base64chars[enc1] + base64chars[enc2];
        result += (i - 1 < bytes.length) ? base64chars[enc3] : '=';
        result += (i < bytes.length) ? base64chars[enc4] : '=';
    }
    
    return result;
}

// ============================================================================
// Hook RAND_bytes - 捕获随机密钥生成
// ============================================================================

setTimeout(function() {
    console.log("[1] Hook RAND_bytes (随机数生成)...");
    
    const randBytes = Module.findExportByName("libcrypto.so", "RAND_bytes");
    if (randBytes) {
        Interceptor.attach(randBytes, {
            onEnter: function(args) {
                this.buf = args[0];
                this.len = args[1].toInt32();
            },
            onLeave: function(retval) {
                if (this.len === 32) {  // AES-256密钥长度
                    try {
                        const key = this.buf.readByteArray(this.len);
                        const keyArray = Array.from(new Uint8Array(key));
                        const keyHex = bytesToHex(keyArray);
                        
                        capturedData.aesKeys.push({
                            hex: keyHex,
                            bytes: keyArray,
                            timestamp: Date.now()
                        });
                        
                        console.log("\n" + "█".repeat(80));
                        console.log("🔑 捕获AES密钥生成 (" + this.len + " bytes)");
                        console.log("█".repeat(80));
                        console.log("HEX: " + keyHex);
                        console.log("这个密钥将被RSA加密后成为ep字段！");
                        console.log("█".repeat(80) + "\n");
                    } catch(e) {
                        console.log("读取密钥失败: " + e);
                    }
                }
            }
        });
        console.log("    ✓ 已Hook RAND_bytes\n");
    }
}, 500);

// ============================================================================
// Hook RSA_public_encrypt - 捕获RSA加密过程
// ============================================================================

setTimeout(function() {
    console.log("[2] Hook RSA_public_encrypt (RSA加密)...");
    
    const rsaEncrypt = Module.findExportByName("libcrypto.so", "RSA_public_encrypt");
    if (rsaEncrypt) {
        let callCount = 0;
        
        Interceptor.attach(rsaEncrypt, {
            onEnter: function(args) {
                this.flen = args[0].toInt32();
                this.from = args[1];
                this.to = args[2];
                this.rsa = args[3];
                this.padding = args[4].toInt32();
                
                if (this.flen === 32) {  // AES密钥长度
                    callCount++;
                    
                    try {
                        const plaintext = this.from.readByteArray(this.flen);
                        const plaintextArray = Array.from(new Uint8Array(plaintext));
                        const plaintextHex = bytesToHex(plaintextArray);
                        
                        capturedData.rsaPlaintext.push({
                            hex: plaintextHex,
                            bytes: plaintextArray,
                            timestamp: Date.now(),
                            callIndex: callCount
                        });
                        
                        console.log("\n" + "█".repeat(80));
                        console.log("🔐 RSA加密调用 #" + callCount);
                        console.log("█".repeat(80));
                        console.log("明文长度: " + this.flen + " bytes (AES密钥)");
                        console.log("填充模式: " + this.padding + " (1=PKCS1, 4=OAEP)");
                        console.log("RSA对象: " + this.rsa);
                        console.log("\n【RSA加密前的明文 (AES密钥)】");
                        console.log("HEX: " + plaintextHex);
                        console.log("STR: " + bytesToString(plaintextArray));
                        
                        // 检查是否匹配之前捕获的AES密钥
                        let matched = false;
                        for (let i = 0; i < capturedData.aesKeys.length; i++) {
                            if (capturedData.aesKeys[i].hex === plaintextHex) {
                                console.log("\n✓ 匹配到之前生成的AES密钥 #" + (i+1));
                                matched = true;
                                break;
                            }
                        }
                        if (!matched) {
                            console.log("\n⚠ 这个密钥在RAND_bytes中未捕获到");
                        }
                        
                        console.log("█".repeat(80) + "\n");
                    } catch(e) {
                        console.log("读取RSA明文失败: " + e);
                    }
                }
            },
            onLeave: function(retval) {
                const resultLen = retval.toInt32();
                
                if (this.flen === 32 && resultLen > 0) {
                    try {
                        const ciphertext = this.to.readByteArray(resultLen);
                        const ciphertextArray = Array.from(new Uint8Array(ciphertext));
                        const ciphertextHex = bytesToHex(ciphertextArray);
                        const ciphertextBase64 = base64Encode(ciphertextArray);
                        
                        capturedData.rsaCiphertext.push({
                            hex: ciphertextHex,
                            base64: ciphertextBase64,
                            bytes: ciphertextArray,
                            timestamp: Date.now(),
                            callIndex: callCount
                        });
                        
                        console.log("\n" + "█".repeat(80));
                        console.log("🔓 RSA加密结果 #" + callCount);
                        console.log("█".repeat(80));
                        console.log("密文长度: " + resultLen + " bytes (通常256字节 = RSA-2048)");
                        console.log("\n【RSA加密后的密文 (将成为ep字段)】");
                        console.log("HEX: " + ciphertextHex);
                        console.log("\n【Base64编码 (这就是ep字段的值)】");
                        console.log(ciphertextBase64);
                        console.log("\n这个Base64字符串将作为ep字段返回！");
                        console.log("█".repeat(80) + "\n");
                    } catch(e) {
                        console.log("读取RSA密文失败: " + e);
                    }
                }
            }
        });
        
        console.log("    ✓ 已Hook RSA_public_encrypt\n");
    }
}, 500);

// ============================================================================
// Hook Base64编码 - 确认ep字段
// ============================================================================

setTimeout(function() {
    try {
        Java.perform(function() {
            console.log("[3] Hook Base64编码...");
            
            const Base64 = Java.use("android.util.Base64");
            
            Base64.encodeToString.overload('[B', 'int').implementation = function(input, flags) {
                const result = this.encodeToString(input, flags);
                
                // ep字段通常很长 (256字节RSA密文 -> ~344字符Base64)
                if (input.length === 256) {
                    const inputArray = [];
                    for (let i = 0; i < input.length; i++) {
                        inputArray.push(input[i] & 0xFF);
                    }
                    const inputHex = bytesToHex(inputArray);
                    
                    capturedData.epValues.push({
                        hex: inputHex,
                        base64: result,
                        timestamp: Date.now()
                    });
                    
                    console.log("\n" + "█".repeat(80));
                    console.log("📤 256字节数据Base64编码 (可能是ep字段)");
                    console.log("█".repeat(80));
                    console.log("输入长度: " + input.length + " bytes");
                    console.log("输入HEX: " + inputHex);
                    console.log("输出长度: " + result.length + " chars");
                    console.log("输出Base64: " + result);
                    
                    // 检查是否匹配RSA密文
                    let matched = false;
                    for (let i = 0; i < capturedData.rsaCiphertext.length; i++) {
                        if (capturedData.rsaCiphertext[i].hex === inputHex) {
                            console.log("\n✓✓✓ 确认：这就是RSA加密后的AES密钥！");
                            console.log("✓✓✓ 这就是ep字段的值！");
                            matched = true;
                            break;
                        }
                    }
                    
                    console.log("█".repeat(80) + "\n");
                }
                
                return result;
            };
            
            console.log("    ✓ 已Hook Base64.encodeToString\n");
        });
    } catch(e) {
        console.log("[!] Java Hook失败: " + e.message);
    }
}, 3000);

// ============================================================================
// 定时汇总报告
// ============================================================================

setTimeout(function() {
    console.log("\n" + "=".repeat(80));
    console.log("📊 EP字段加密分析汇总");
    console.log("=".repeat(80));
    
    console.log("\n【捕获统计】");
    console.log("  - AES密钥生成: " + capturedData.aesKeys.length + " 次");
    console.log("  - RSA加密明文: " + capturedData.rsaPlaintext.length + " 次");
    console.log("  - RSA加密密文: " + capturedData.rsaCiphertext.length + " 次");
    console.log("  - EP字段候选: " + capturedData.epValues.length + " 个");
    
    if (capturedData.rsaCiphertext.length > 0) {
        console.log("\n【EP字段加密流程总结】");
        console.log("  1. 生成32字节随机AES密钥");
        console.log("  2. 使用RSA-2048公钥加密这个AES密钥");
        console.log("  3. RSA加密输出256字节密文");
        console.log("  4. 对256字节密文进行Base64编码");
        console.log("  5. Base64结果即为ep字段的值");
        
        console.log("\n【关键参数】");
        console.log("  - 加密算法: RSA");
        console.log("  - 密钥长度: 2048 bits (256 bytes)");
        console.log("  - 填充方式: PKCS1Padding");
        console.log("  - 明文: 32字节AES密钥");
        console.log("  - 密文: 256字节");
        console.log("  - 编码: Base64");
        
        console.log("\n【示例数据】");
        for (let i = 0; i < Math.min(3, capturedData.rsaCiphertext.length); i++) {
            const item = capturedData.rsaCiphertext[i];
            console.log("\n  EP #" + (i+1) + ":");
            console.log("  Base64: " + item.base64.substring(0, 60) + "...");
            console.log("  长度: " + item.base64.length + " 字符");
        }
    }
    
    console.log("\n" + "=".repeat(80));
    console.log("✓ 分析完成！");
    console.log("=".repeat(80) + "\n");
    
}, 15000);  // 15秒后输出汇总

console.log("=".repeat(80));
console.log("✓ EP分析Hook已就绪");
console.log("=".repeat(80) + "\n");

